package org.kia.data;

import java.lang.reflect.Type;
import java.util.List;

import org.kia.data.adapters.RequestAdapter;
import org.kia.data.adapters.RequestFactory;
import org.kia.data.interfaces.OnDataReceivedListener;
import org.kia.data.model.CategoryModel;
import org.kia.data.model.ItemModel;
import org.kia.manager.SettingsManager;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;

import com.github.droidfu.cachefu.CachedModel;
import com.google.gson.reflect.TypeToken;

/**
 * Proxy for data requests
 *
 * @author Amir Lazarovich
 */
@SuppressWarnings("rawtypes") 
public class DataProxy {

	//////////////////////////////////////////////
	// Members
	//////////////////////////////////////////////

    private static String mServerAddress = null;

	//////////////////////////////////////////////
	// Public
	//////////////////////////////////////////////

    /**
     * Request asynchronously data from the server. <br/> <u>Usage example</u>:<br/> get(MethodTypeEnum.CATEGORIES, context,
     * requestParameters, callback);
     *
     * @param method                      {@link MethodType} - responsible for the type of the request
     * @param context                     The context where you operate from. Used for SharedPreferences, contentResolver and more
     *                                    by the {@link DataController}
     * @param params                      Request parameters
     * @param listener                    Callback when the request is received
     * @param <T>
     * @return
     */
    public synchronized static <T extends CachedModel> AsyncTask<RequestAdapter, Integer, List<T>> get(MethodType method, Context context,
                                                                                                                        Bundle params, OnDataReceivedListener listener) {
        // Init data controller
        DataController dc = new DataController(context, listener);

        // Get server address
        String serverAddress = getServerAddress(context);

        // Prepare Http request
        RequestAdapter request = RequestFactory.createGetRequest(serverAddress + method.getName(), params);

        // Request data
        return dc.getDataAsync(method.getType(), request.getKey(), request);
    }

	//////////////////////////////////////////////
	// Private
	//////////////////////////////////////////////

    /**
     * Get the server address (once)
     *
     * @param context
     * @return
     */
    private static String getServerAddress(Context context) {
        if (mServerAddress == null) {
            mServerAddress = SettingsManager.getInstance().getServerAddress(context);
        }

        return mServerAddress;
    }

    //////////////////////////////////////////////
	// Inner classes 
	//////////////////////////////////////////////
    
    /**
     * Enumerate all method types
     */
    public static enum MethodType {
        CATEGORIES("categories", new TypeToken<List<CategoryModel>>(){}.getType()),
        ITEMS_IN_CATEGORY("places", new TypeToken<List<ItemModel>>(){}.getType()),
        ITEM("places/{id}", new TypeToken<ItemModel>(){}.getType());

        private String mName;
        private Type mType;

        MethodType(String name, Type type) {
            mName = name;
            mType = type;
        }

        public static MethodType fromString(String text) {
            if (text != null) {
                for (MethodType methodType : MethodType.values()) {
                    if (text.equalsIgnoreCase(methodType.mName)) {
                        return methodType;
                    }
                }
            }
            return null;
        }

        public String toString() {
            return mName;
        }

        public String getName() {
            return mName;
        }

        public void setName(String mName) {
            this.mName = mName;
        }

        public Type getType() {
            return mType;
        }

        public void setType(Type mType) {
            this.mType = mType;
        }
    }
}
